import sys

import requests
import json
import os
import time
import xlrd  # 用于读取xls格式文件
from typing import List, Dict, Optional
from datetime import datetime

# 全局变量定义（集中管理配置和状态）
BASE_URL = "https://caigou.chinatelecom.com.cn"
TOKEN = ""
EXPORT_PATH = ""
DOWNLOAD_ROOT = ""
LOGGER = None
START_TIME = ""
END_TIME = ""
ORDER_CODE = ""
CONTRACT_CODE=""
PAGE_SIZE = 20  # 每页订单数量
JWT_SUPPLIER=""
COOKIE_D8D3A8C = ""
class LOGGER:
    """日志工具类，同时输出到控制台和文件"""

    def __init__(self, log_file_path: str):
        log_dir = os.path.dirname(log_file_path)
        if not os.path.exists(log_dir):
            os.makedirs(log_dir, exist_ok=True)
        self.log_file = log_file_path

    def print(self, message: str) -> None:
        """打印并写入日志（带时间戳）"""
        print(message)
        with open(self.log_file, 'a', encoding='utf-8') as f:
            timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            f.write(f"[{timestamp}] {message}\n")


def init_global_vars(args: Optional[List[str]] = None) -> None:
    """初始化所有全局变量（集中配置）"""
    global BASE_URL, TOKEN, EXPORT_PATH, DOWNLOAD_ROOT, LOGGER,START_TIME,END_TIME,ORDER_CODE,CONTRACT_CODE,JWT_SUPPLIER,COOKIE_D8D3A8C

    # 基础配置
    BASE_URL = "https://caigou.chinatelecom.com.cn"
    EXPORT_PATH = args[5]  # 导出根路径
    CONTRACT_CODE = args[1]  # 合同编号（单独提取便于维护）
    DOWNLOAD_ROOT = os.path.join(EXPORT_PATH, f"招投标合同发票证明材料\\"+CONTRACT_CODE)
    START_TIME = args[3]
    END_TIME = args[4]
    # 初始化日志
    log_file = os.path.join(EXPORT_PATH, "export_log.txt")
    LOGGER = LOGGER(log_file)
    token_data = json.loads(args[0])
    LOGGER.print(f"token_data: {token_data}")
    JWT_SUPPLIER = token_data["cookie"]["JWT_SUPPLIER"]
    LOGGER.print(f"JWT_SUPPLIER: {JWT_SUPPLIER}")
    COOKIE_D8D3A8C = token_data["cookie"]["F054DEE9C0A57972ADF303BF51509DD36EC9F44B5A43AB55"]
    LOGGER.print(f"F054DEE9C0A57972ADF303BF51509DD36EC9F44B5A43AB55: {COOKIE_D8D3A8C}")
    # token = token_data["localStorage"]["Admin-Token"]

    LOGGER.print(f"导出路径: {EXPORT_PATH}")
    LOGGER.print(f"合同编号: {CONTRACT_CODE}")
    LOGGER.print(f"下载根目录: {DOWNLOAD_ROOT}")
    LOGGER.print(f"开始时间: {START_TIME}")
    LOGGER.print(f"结束时间: {END_TIME}")
    LOGGER.print(f"Token: {TOKEN}")

    # 初始化Token（实际使用时建议从安全渠道获取）
    #TOKEN = "eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjBjN2Q1YWM1LWFjM2MtNDNiNS04Nzc5LWUxOTU5ZDE0ZWQ1YSJ9.N-7BzXFbQZWneVeBvAspz6k9up5qbjNn4GLgj3-wuuCO6skrmI6uWZH7sIejcfV0j9eMC9h3ow9LnEcq2xmm6g"

    # 初始化下载根目录
    try:
        os.makedirs(DOWNLOAD_ROOT, exist_ok=True)
        LOGGER.print(f"下载根目录: {os.path.abspath(DOWNLOAD_ROOT)}")
    except OSError as e:
        LOGGER.print(f"创建下载目录失败: {str(e)}")


def export_settlement_excel(save_path: str) -> str:
    """导出结算单Excel文件（保持不变）"""
    url = 'http://www.tower.com.cn/settlement/v1/export/export-excel'

    headers = {
        'Accept': 'application/json, text/plain, */*',
        'Accept-Language': 'zh-CN,zh;q=0.9,ru;q=0.8',
        'Connection': 'keep-alive',
        'Content-Type': 'application/json;charset=UTF-8',
        'D690E1F32E5C0A5B9EDEDF6235F9F97A': 'undefined',
        'Origin': 'http://www.tower.com.cn',
        'Referer': 'http://www.tower.com.cn/eshop/v2/settlement/front/',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36',
    }
    cookies = {
        'ULTRA_U_K': '',
        'CAPTCHA_UUID_PORTAL': 'f0301a9f-6517-4027-8421-e0f9e908ea3c',
        'QkNOX0VT': 'RVNIT1BfRlJPTlRfQ09PS0lFX05BTUU=',
        'RVhUX0NL': 'RVNIT1BfRlJPTlRfRVhURU5EX0NPT0tJRV9OQU1F',
        'F054DEE9C0A57972833B3BE0209CBBAFA5F3BAF6F12C50BB9C3C06A11C819CF5': 'F6B78599F7AE09F09113CDE0A3514E61377E7C00060C028A884D67A1B0636ED1',
        'JWT_SUPPLIER': JWT_SUPPLIER,
        'F054DEE9C0A57972ADF303BF51509DD36EC9F44B5A43AB55': COOKIE_D8D3A8C,
    }

    data = {
        "fileName": "结算单详情.xls",
        "exportType": "SETTLE_SETTLEMENTDETAILBACKFILL_EXPORT",
        "data": {
            "materialType": "1",
            "contractCode": CONTRACT_CODE,
            "orgName": "",
            "supplyName": "",
            "invoiceNumber": "",
            "statusList": [],
            "settleStartDate": START_TIME,
            "settleEndDate": END_TIME,
            "orderCode": "",
            "settlementCode": "",
            "accountCode": "",
            "invoiceCode": "",
            "gsAccountCode": "",
            "gsSettleStartDate": None,
            "gsSettleEndDate": None,
            "businessType": "",
            "page": 1,
            "pageSize": 10000,
            "queryType": 2,
            "ids": []
        }
    }

    try:
        response = requests.post(
            url,
            headers=headers,
            cookies=cookies,
            json=data,
            verify=False,
            stream=True
        )
        response.raise_for_status()
        LOGGER.print(data)
        os.makedirs(os.path.dirname(save_path), exist_ok=True)
        save_path = os.path.join(save_path, "结算单.xls")  # 拼接文件夹和文件名，形成完整文件路径

        with open(save_path, 'wb') as f:
            for chunk in response.iter_content(chunk_size=1024):
                if chunk:
                    f.write(chunk)

        LOGGER.print(f"Excel文件导出成功，已保存至：{save_path}")
        return save_path

    except Exception as e:
        LOGGER.print(f"Excel导出失败: {e}")
        return save_path


def extract_purchase_order_numbers(excel_path: str):
    """
    从xls格式Excel中提取采购订单号和合同编号

    返回:
        元组 (order_numbers, contract_numbers)，分别为采购订单号列表和合同编号列表
        若文件不存在或异常，返回 ([], [])
    """
    if not os.path.exists(excel_path):
        print(f"Excel文件不存在: {excel_path}")
        return [], []  # 统一返回元组

    try:
        workbook = xlrd.open_workbook(excel_path)
        worksheet = workbook.sheet_by_index(0)

        # 查找列（修正：不中断循环，确保两列都能被找到）
        order_column = None
        contract_column = None
        for col in range(worksheet.ncols):
            header_value = str(worksheet.cell_value(0, col)).strip()
            if header_value == "采购订单号":
                order_column = col
            if header_value == "结算单号":
                contract_column = col  # 注意：这里去掉break，允许同时查找两列

        # 校验列是否存在
        if order_column is None:
            print("未找到列名【采购订单号】，无法提取采购订单号")
            return [], []
        if contract_column is None:
            print("未找到列名【合同编号】，无法提取结算单号")
            return [], []

        # 提取数据（合并循环，一次遍历完成）
        order_numbers = []
        contract_numbers = []
        for row in range(1, worksheet.nrows):
            # 提取采购订单号
            order_val = str(worksheet.cell_value(row, order_column)).strip()
            if order_val:
                order_numbers.append(order_val)
            # 提取合同编号
            contract_val = str(worksheet.cell_value(row, contract_column)).strip()
            if contract_val:
                contract_numbers.append(contract_val)

        print(f"从Excel中提取到 {len(order_numbers)} 个采购订单号，{len(contract_numbers)} 个合同编号")
        return order_numbers, contract_numbers

    except Exception as e:
        print(f"提取失败: {e}")
        return [], []  # 异常时也返回元组，保证类型一致


def download_order_pdf(order_no: str, save_dir: str, cookies: Optional[Dict] = None) -> bool:
    """下载单个采购订单的PDF文件（保持不变）"""
    if not order_no:
        LOGGER.print("订单号为空，跳过下载")
        return False

    # 创建保存目录
    os.makedirs(save_dir, exist_ok=True)
    save_path = os.path.join(save_dir, f"{order_no}.pdf")

    # 如果文件已存在，跳过下载
    if os.path.exists(save_path):
        LOGGER.print(f"PDF文件已存在，跳过下载: {save_path}")
        return True

    url = 'http://www.tower.com.cn/eshop/v2/report/online/onlineOrderExportPdf'

    headers = {
        'Accept': 'application/json, text/plain, */*',
        'Accept-Language': 'zh-CN,zh;q=0.9,ru;q=0.8',
        'Connection': 'keep-alive',
        'Content-Type': 'application/json;charset=UTF-8',
        'Origin': 'http://www.tower.com.cn',
        'Referer': 'http://www.tower.com.cn/pshop/v2/stage/front/',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36',
    }

    # 使用提供的cookies或默认cookies
    if not cookies:
        cookies = {
            'JSESSIONID': '7228EB8BDDD9A44C2D6A102CCF2590EC.node2',
            'ULTRA_U_K': '',
            'CAPTCHA_UUID_PORTAL': 'f0301a9f-6517-4027-8421-e0f9e908ea3c',
            'QkNOX0VT': 'RVNIT1BfRlJPTlRfQ09PS0lFX05BTUU=',
            'RVhUX0NL': 'RVNIT1BfRlJPTlRfRVhURU5EX0NPT0tJRV9OQU1F',
            'F054DEE9C0A57972833B3BE0209CBBAFA5F3BAF6F12C50BB9C3C06A11C819CF5': 'F6B78599F7AE09F09113CDE0A3514E61377E7C00060C028A884D67A1B0636ED1',
            'F054DEE9C0A57972ADF303BF51509DD36EC9F44B5A43AB55': COOKIE_D8D3A8C,
            'JWT_SUPPLIER': JWT_SUPPLIER
        }

    data = {
        "orderNo": order_no,
        "startNoticeDate": "",
        "endNoticeDate": "",
        "projectCode": "",
        "receiptName": "",
        "address": "",
        "orgName": "",
        "provinceName": "",
        "headIdList": [],
        "supplierCode": "020100003072",
        "slaveSupplierCode": "020100003072",
        "type": "PRIMARY"
    }

    try:
        LOGGER.print(f"开始下载订单 {order_no} 的PDF文件...")
        response = requests.post(
            url,
            headers=headers,
            cookies=cookies,
            json=data,
            verify=False,
            stream=True
        )
        response.raise_for_status()

        # 检查响应内容是否为PDF
        content_type = response.headers.get('Content-Type', '')
        if 'pdf' not in content_type.lower():
            LOGGER.print(f"警告: 订单 {order_no} 返回的不是PDF文件，内容类型: {content_type}")
            return False

        # 保存PDF文件
        with open(save_path, 'wb') as f:
            for chunk in response.iter_content(chunk_size=1024):
                if chunk:
                    f.write(chunk)

        LOGGER.print(f"订单 {order_no} 的PDF文件已保存至: {save_path}")
        return True

    except Exception as e:
        LOGGER.print(f"下载订单 {order_no} 的PDF文件失败: {e}")
        return False


def main():
    # 获取命令行参数
    args = sys.argv[1:]
    if len(args) < 7:
        LOGGER.print(
            "参数错误！使用方式: python script.py [token] [框架合同编号] [商品名称] [开始时间] [结束时间] [导出路径] [目录结构标识]")
        sys.exit(1)
    """主函数：初始化并执行流程"""
    init_global_vars(args)

    request_interval = 3  # 请求间隔时间（秒）

    LOGGER.print("===== 开始执行采购订单PDF下载流程 =====")

    # 1. 导出结算单Excel
    save_path=export_settlement_excel(DOWNLOAD_ROOT)

    # 等待Excel文件完全写入
    time.sleep(2)

    # 2. 从Excel中提取采购订单号
    order_numbers ,contract_numbers = extract_purchase_order_numbers(save_path)
    if not order_numbers:
        LOGGER.print("未提取到采购订单号，终止流程")
        return

    # 3. 批量下载PDF文件
    success_count = 0
    fail_count = 0
    for i, order_no in enumerate(order_numbers, 1):
        download_dir = os.path.join(DOWNLOAD_ROOT, contract_numbers[i])
        LOGGER.print(f"\n处理第 {i}/{len(order_numbers)} 个订单")
        if should_stop():
            print("")
            break
        #用框架合同号作为一级目录
        pdf_save_dir = os.path.join(download_dir, order_no)
        if download_order_pdf(order_no, pdf_save_dir):
            success_count += 1
        else:
            fail_count += 1

        # 最后一个订单不添加间隔
        if i < len(order_numbers):
            time.sleep(request_interval)

    # 4. 输出结果统计
    LOGGER.print("\n===== 下载流程完成 =====")
    LOGGER.print(f"总订单数: {len(order_numbers)}")
    LOGGER.print(f"下载成功: {success_count}")
    LOGGER.print(f"下载失败: {fail_count}")
    LOGGER.print(f"PDF文件保存目录: {pdf_save_dir}")


if __name__ == "__main__":
    main()
